import { defineStore } from "pinia";
import { onUnmounted, ref, Ref, unref, watch } from "vue";
import { getLogger } from "../../../ts/log";

interface store {
  maps: Map<string, any>;
}

export const usePageDataStore = defineStore({
  // 它用于 devtools 并允许恢复状态
  id: "pageData",
  state: (): store => {
    return {
      maps: new Map<string, any>(),
    };
  },
  actions: {
    /**
     * 向页面数据存储结构中存储数据
     *
     * 此数据主要用于页面状态缓存
     *
     * @param name 存储的名称
     * @param data 存储数据
     * @param saveLocalStorage 是否存储到 localStorage 中
     */
    setData<T = any>(name: string, data: T, saveLocalStorage = false) {
      if (saveLocalStorage) {
        localStorage.setItem(name, JSON.stringify(data));
      } else {
        this.maps.set(name, data);
      }
    },
    /**
     * 从页面数据存储器中读取数据
     * @param name
     * @param readLocalStorage 是否从 localStorage 中读取数据
     */
    getData<T = any>(name: string, readLocalStorage = false): T | undefined {
      if (readLocalStorage) {
        const item = localStorage.getItem(name);
        return item ? JSON.parse(item) : undefined;
      } else {
        return this.maps.get(name);
      }
    },
    deleteData(name: string): boolean {
      return this.maps.delete(name);
    },
  },
});

export interface PageDataOptions<T> {
  name: string; // 存储的唯一名称
  data: T | Ref<T>; // 数据实体
  useLocalStorage?: boolean; // 是否存储到 localStorage 中，默认 false
  delay?: number; // 防抖延时
}
/**
 * 使用页面数据
 * @param options 输入参数
 */
export function usePageData<T = undefined>(options: PageDataOptions<T>) {
  const { name, data, useLocalStorage = false, delay = 5000 } = options;

  const logger = getLogger("ys-ts.vue.use.page_data");

  const store = usePageDataStore();
  const d = store.getData<T>(name, useLocalStorage);
  logger(name, d);
  const dataValue: T = unref(data);

  const pageData = ref<T>(dataValue) as Ref<T>;
  if (d !== undefined) {
    pageData.value = { ...dataValue, ...d };
  }

  // 数据存储函数
  let timer: NodeJS.Timeout | null = null;

  function clearTimer() {
    if (timer !== null) {
      clearTimeout(timer);
    }
  }

  const save = () => {
    clearTimer();
    store.setData<T>(name, pageData.value, useLocalStorage);
  };

  // 监控防抖
  watch(
    pageData,
    () => {
      logger("数据改变", name);
      if (delay > 0) {
        clearTimer();
        timer = setTimeout(() => {
          timer = null;
          save();
        }, delay);
      } else {
        save();
      }
    },
    {
      deep: true,
    }
  );

  onUnmounted(() => {
    logger("Unmounted", name);
    save();
  });

  return { pageData };
}

export function usePageData2<T = undefined>(options: PageDataOptions<T>) {
  const { name, data, delay = 5000 } = options;
  const useLocalStorage = false;

  const logger = getLogger("ys-ts.vue.use.page_data");

  const store = usePageDataStore();
  const d = store.getData<Ref<T>>(name, useLocalStorage);
  logger(name, d);
  const dataValue: T = unref(data);
  let pageData = d;

  // 数据存储函数
  let timer: NodeJS.Timeout | null = null;

  function clearTimer() {
    if (timer !== null) {
      clearTimeout(timer);
    }
  }

  const save = () => {
    clearTimer();
    store.setData<Ref<T>>(name, pageData!, useLocalStorage);
  };

  // 没有数据时用默认参数初始化
  if (pageData === undefined) {
    pageData = ref(dataValue) as Ref<T>;
    save();
  }

  // 监控防抖
  watch(
    pageData,
    () => {
      logger("数据改变", name);
      if (delay > 0) {
        clearTimer();
        timer = setTimeout(() => {
          timer = null;
          save();
        }, delay);
      } else {
        save();
      }
    },
    {
      deep: true,
    }
  );

  onUnmounted(() => {
    logger("Unmounted", name);
    save();
  });

  return { pageData };
}
